package config

import (
	"bytes"
	"com.lh.user.service/pb/user"
	"errors"
	"fmt"
	"gopkg.in/yaml.v3"
	"os"
	"reflect"
	"regexp"
	"strings"
	"sync"
)

type Options struct {
	Namespace string
	Name      string
	Version   string
	Paths     map[string]string
	Database  map[string]user.ServeConfig
	Serve     map[string]user.ServeConfig
}

var cache sync.Map

func Init(path string, key string) (*user.ServeConfig, error) {
	reg := regexp.MustCompile(`/com.lh.lh.work/`)
	root := path
	if reg.MatchString(path) {
		text := bytes.NewReader([]byte(path))
		loc := reg.FindReaderIndex(text)
		root = path[:loc[1]-1]
	}
	index := strings.LastIndex(path, "/")
	filename := fmt.Sprintf("%s/config/local.config.yaml", root)
	files, err := os.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	options := &Options{}
	if err = yaml.Unmarshal(files, &options); err != nil {
		return nil, err
	}
	options.Paths["root"] = root
	options.Paths["path"] = path
	options.Name = path[index+1:]
	list := options.Serve
	serve, ok := list[key]
	if !ok {
		return nil, errors.New("key not found")
	}
	if IsStore() {
		SetServe(key, &serve)
	} else {
		cache.Store("com.lh.lh.work", options)
	}
	return &serve, nil
}
func IsStore() bool {
	_, ok := cache.Load("com.lh.lh.work")
	return ok
}
func GetServe(key string) *user.ServeConfig {
	if val, ok := cache.Load("com.lh.lh.work"); ok {
		if data, ok := val.(*Options); ok {
			if val, ok := data.Serve[key]; ok {
				return &val
			}
			return &user.ServeConfig{}
		}
		return &user.ServeConfig{}
	}
	return &user.ServeConfig{}
}

func SetServe(key string, opts *user.ServeConfig) *user.ServeConfig {
	if val, ok := cache.Load("com.lh.lh.work"); ok {
		if data, ok := val.(*Options); ok {
			data.Serve[key] = *opts
			cache.Store("com.lh.lh.work", data)
		}
		return &user.ServeConfig{}
	}
	return &user.ServeConfig{}
}

func GetKey(key string) string {
	if val, ok := cache.Load("com.lh.lh.work"); ok {
		if data, ok := val.(*Options); ok {
			val := reflect.ValueOf(data)
			str := val.FieldByName(key)
			if str.Kind() == reflect.String {
				return str.String()
			} else {
				return ""
			}
		}
		return ""
	}
	return ""

}

func GetPath(key string) *string {
	if val, ok := cache.Load("com.lh.lh.work"); ok {
		if data, ok := val.(*Options); ok {
			if val, ok := data.Paths[key]; ok {
				return &val
			}
			return nil
		}
		return nil
	}
	return nil
}

func GetData(key string) *user.ServeConfig {
	if val, ok := cache.Load("com.lh.lh.work"); ok {
		if data, ok := val.(*Options); ok {
			if val, ok := data.Database[key]; ok {
				return &val
			}
			return &user.ServeConfig{}
		}
		return &user.ServeConfig{}
	}
	return &user.ServeConfig{}
}

func SetData(key string, opts *user.ServeConfig) *user.ServeConfig {
	if val, ok := cache.Load("com.lh.lh.work"); ok {
		if data, ok := val.(*Options); ok {
			data.Database[key] = *opts
			cache.Store("com.lh.lh.work", data)
		}
		return &user.ServeConfig{}
	}
	return &user.ServeConfig{}
}

func UpdateData(key string, data *user.ServeConfig) error {
	if val, ok := cache.Load("com.lh.lh.work"); ok {
		if opts, ok := val.(*Options); ok {
			opts.Database[key] = *data
			path := GetPath("path")
			filename := fmt.Sprintf("%v/config/local.config.yaml", path)
			bytes, err := yaml.Marshal(opts)
			if err != nil {
				return err
			}
			if err = os.WriteFile(filename, bytes, 0755); err != nil {
				return err
			}
		}
		return errors.New("反序列化数据错误")
	}
	return errors.New("未查询到有效数据")
}
